from typing import Optional, List, Tuple, Dict, Any
from tortoise.exceptions import DoesNotExist
from app.modules.permissions.models import PermissionModel
from app.modules.permissions.schemas import (
    PermissionCreateInput, PermissionCreatedResponse, PermissionUpdate, 
    PermissionInfo, PermissionTreeItem, PermissionQueryParams
)
from app.core.exceptions import BusinessException, NotFoundException


class PermissionService:
    """权限服务类"""

    @staticmethod
    async def get_by_id(permission_id: int) -> Optional[PermissionModel]:
        """通过ID获取权限"""
        permission = await PermissionModel.get_or_none(id=permission_id)
        if not permission:
            raise NotFoundException(message="权限不存在")
        return permission

    @staticmethod
    async def get_by_code(code: str) -> Optional[PermissionModel]:
        """通过编码获取权限"""
        return await PermissionModel.get_or_none(code=code)

    @staticmethod
    async def get_permission_list(
        skip: int = 0, 
        limit: int = 10,
        query_params: Optional[PermissionQueryParams] = None
    ) -> Tuple[int, List[PermissionInfo]]:
        """获取权限列表（带分页和查询条件）"""
        query = PermissionModel.all()
        
        # 应用查询条件
        if query_params:
            if query_params.name:
                query = query.filter(name__icontains=query_params.name)
            if query_params.code:
                query = query.filter(code__icontains=query_params.code)
            if query_params.type:
                query = query.filter(type=query_params.type)
            if query_params.parent_id is not None:
                query = query.filter(parent_id=query_params.parent_id)
            if query_params.is_active is not None:
                query = query.filter(is_active=query_params.is_active)
            if query_params.is_visible is not None:
                query = query.filter(is_visible=query_params.is_visible)
            if query_params.is_system is not None:
                query = query.filter(is_system=query_params.is_system)
        
        total = await query.count()
        permissions = await query.offset(skip).limit(limit).order_by('sort_order', 'id')
        
        # 转换为Pydantic模型
        permission_info_list = [PermissionInfo.from_orm(permission) for permission in permissions]
        return total, permission_info_list

    @staticmethod
    async def create_permission(permission_data: PermissionCreateInput) -> PermissionCreatedResponse:
        """创建权限"""
        # 检查权限编码是否已存在
        if await PermissionService.get_by_code(permission_data.code):
            raise BusinessException(message="权限编码已存在")
        
        # 检查父级权限是否存在
        if permission_data.parent_id != 0:
            parent_permission = await PermissionService.get_by_id(permission_data.parent_id)
            if not parent_permission:
                raise BusinessException(message="父级权限不存在")
        
        permission = await PermissionModel.create(**permission_data.dict())
        
        return PermissionCreatedResponse(
            id=permission.id,
            name=permission.name,
            code=permission.code
        )

    @staticmethod
    async def update_permission(permission_id: int, permission_data: PermissionUpdate) -> PermissionInfo:
        """更新权限信息"""
        permission = await PermissionService.get_by_id(permission_id)
        
        # 检查是否为系统权限
        if permission.is_system:
            raise BusinessException(message="系统权限不允许修改")
        
        # 检查权限编码是否重复（排除自己）
        if permission_data.code and permission_data.code != permission.code:
            existing_permission = await PermissionService.get_by_code(permission_data.code)
            if existing_permission:
                raise BusinessException(message="权限编码已存在")
        
        # 检查父级权限是否存在
        if permission_data.parent_id is not None and permission_data.parent_id != 0:
            if permission_data.parent_id == permission_id:
                raise BusinessException(message="不能将自己设为父级权限")
            parent_permission = await PermissionService.get_by_id(permission_data.parent_id)
            if not parent_permission:
                raise BusinessException(message="父级权限不存在")
        
        # 更新权限信息
        update_data = permission_data.dict(exclude_unset=True)
        for key, value in update_data.items():
            setattr(permission, key, value)
        await permission.save()
        
        return PermissionInfo.from_orm(permission)

    @staticmethod
    async def delete_permission(permission_id: int) -> None:
        """删除权限"""
        permission = await PermissionService.get_by_id(permission_id)
        
        # 检查是否为系统权限
        if permission.is_system:
            raise BusinessException(message="系统权限不允许删除")
        
        # 检查是否有子权限
        children = await permission.get_children()
        if children:
            raise BusinessException(message="存在子权限，无法删除")
        
        # 检查是否有角色使用此权限
        from app.modules.roles.models import RoleModel
        roles_with_permission = await RoleModel.filter(permissions__contains=[permission.code])
        if roles_with_permission:
            raise BusinessException(message="有角色正在使用此权限，无法删除")
        
        await permission.delete()

    @staticmethod
    async def get_permission_tree() -> List[PermissionTreeItem]:
        """获取权限树结构"""
        async def build_tree(parent_id: int = 0) -> List[PermissionTreeItem]:
            permissions = await PermissionModel.filter(
                parent_id=parent_id, 
                is_active=True
            ).order_by('sort_order', 'id')
            
            tree = []
            for permission in permissions:
                children = await build_tree(permission.id)
                tree_item = PermissionTreeItem(
                    id=permission.id,
                    name=permission.name,
                    code=permission.code,
                    type=permission.type,
                    parent_id=permission.parent_id,
                    path=permission.path,
                    component=permission.component,
                    icon=permission.icon,
                    sort_order=permission.sort_order,
                    is_visible=permission.is_visible,
                    children=children
                )
                tree.append(tree_item)
            return tree
        
        return await build_tree()

    @staticmethod
    async def get_menus() -> List[PermissionInfo]:
        """获取所有菜单权限"""
        permissions = await PermissionModel.get_menus()
        return [PermissionInfo.from_orm(permission) for permission in permissions]

    @staticmethod
    async def get_buttons() -> List[PermissionInfo]:
        """获取所有按钮权限"""
        permissions = await PermissionModel.get_buttons()
        return [PermissionInfo.from_orm(permission) for permission in permissions]

    @staticmethod
    async def get_apis() -> List[PermissionInfo]:
        """获取所有接口权限"""
        permissions = await PermissionModel.get_apis()
        return [PermissionInfo.from_orm(permission) for permission in permissions]

    @staticmethod
    async def get_root_permissions() -> List[PermissionInfo]:
        """获取根级权限"""
        permissions = await PermissionModel.get_root_permissions()
        return [PermissionInfo.from_orm(permission) for permission in permissions]

    @staticmethod
    async def get_permission_children(permission_id: int) -> List[PermissionInfo]:
        """获取权限的子权限"""
        permission = await PermissionService.get_by_id(permission_id)
        children = await permission.get_children()
        return [PermissionInfo.from_orm(child) for child in children]

    @staticmethod
    async def get_permission_ancestors(permission_id: int) -> List[PermissionInfo]:
        """获取权限的祖先权限"""
        permission = await PermissionService.get_by_id(permission_id)
        ancestors = await permission.get_ancestors()
        return [PermissionInfo.from_orm(ancestor) for ancestor in ancestors]

    @staticmethod
    async def get_permission_descendants(permission_id: int) -> List[PermissionInfo]:
        """获取权限的后代权限"""
        permission = await PermissionService.get_by_id(permission_id)
        descendants = await permission.get_descendants()
        return [PermissionInfo.from_orm(descendant) for descendant in descendants]

    @staticmethod
    async def batch_update_permissions(permission_ids: List[int], update_data: Dict[str, Any]) -> None:
        """批量更新权限"""
        # 检查是否为系统权限
        system_permissions = await PermissionModel.filter(
            id__in=permission_ids, 
            is_system=True
        )
        if system_permissions:
            raise BusinessException(message="系统权限不允许批量修改")
        
        # 批量更新
        await PermissionModel.filter(id__in=permission_ids).update(**update_data)

    @staticmethod
    async def get_permissions_by_codes(codes: List[str]) -> List[PermissionInfo]:
        """根据权限编码列表获取权限"""
        permissions = await PermissionModel.filter(code__in=codes, is_active=True)
        return [PermissionInfo.from_orm(permission) for permission in permissions]
